﻿using Activity.Helper;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Activity
{
    public class BaseHandler : IHttpHandler
    {
      public  readonly Dictionary<int, string> messageCode = new Dictionary<int, string>(){
            { 40001 ,"无效的OpenID" },
            { 40002 ,"超出活动时间范围" },
            { 40003 ,"请先注册会员" },
            { 40004 ,"用户不存在" },
            { 40005 ,"无效的[Code]值" },
            { 40006 ,"非KM会员" },
            { 40009 ,"数据异常" },
            { 1 ,"成功" }
        };

        /// <summary>
        /// 指定过来的http请求类型  主要指定action方法名称的接收方式 get 或者 post
        /// </summary>
        protected NameValueCollection _httpReuqest = HttpContext.Current.Request.Form;

        protected HttpRequest Request = HttpContext.Current.Request;

        /// <summary>
        /// 指定返回头
        /// </summary>
        protected string _contentType = "text/plain";

        /// <summary>
        /// 指定接收action方法的参数名称
        /// </summary>
        protected string _actionName = "action";

        //获取当前的http context
        protected HttpContext Context
        {
            get
            {
                return HttpContext.Current;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = this._contentType;

            try
            {
                //动态调用方法 当然  你还可以在这里加上是否为同域名请求的判断
                this.DynamicMethod();
            }
            catch (AmbiguousMatchException amEx)
            {
                this.Error(string.Format("根据该参数{0}找到了多个方法", amEx.Message));
            }
            catch (ArgumentException argEx)
            {
                this.Error("参数异常" + argEx.Message);
            }
            catch (ApplicationException apEx)
            {
                this.Error("程序异常" + apEx.Message);
            }

        }

        #region 动态调用方法
        /// <summary>
        /// 动态调用方法
        /// </summary>
        private void DynamicMethod()
        {
            //根据指定的请求类型获取方法名
            string action = this._httpReuqest[this._actionName];
            if (this.Request[this._actionName] != null)
            {
                action = this.Request[this._actionName];
            }
            if (!string.IsNullOrEmpty(action))
            {
                //获取方法的实例  非静态 需要Public访问权限 忽略大小写
                MethodInfo methodInfo = this.GetType().GetMethod(action, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase);
                if (methodInfo != null)
                {
                    //调用方法
                    methodInfo.Invoke(this, null);
                }
                else
                {
                    throw new ApplicationException(string.Format("没有找到方法{0}", action));
                }
            }
            else
            {
                throw new ArgumentNullException("没有找到调用方法参数或者方法名为空");
            }
        }
        #endregion

        #region 打印Json的相关处理
        /// <summary>
        /// 执行Action时发生错误请调用此方法
        /// </summary>
        /// <param name="Message"></param>
        /// <param name="code"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        protected void Error(string Message, int code = -1, object data = null)
        {
            //Log.Error("执行API发生错误:{0}\n{1}", "API", Message, code);
            var response = this.Context.Response;
            SetHeader(response);
            response.AddHeader("Content-Type", "application/json");
            response.Write((new ApiResult()
            {
                Success = false,
                Code = code,
                Message = Message,
                Data = data
            }).ToJson());
        }

        /// <summary>
        /// 打印成功处理的json
        /// </summary>
        /// <param name="obj"></param>
        protected void Success(object obj)
        {
            var response = this.Context.Response;
            SetHeader(response);
            response.AddHeader("Content-Type", "application/json");
            response.Write((new ApiResult()
            {
                Success = true,
                Data = obj
            }).ToJson());
        }

        /// <summary>
        /// 打印json
        /// </summary>
        /// <param name="state"></param>
        /// <param name="msg"></param>
        protected void output(object r)
        {
            var response = this.Context.Response;

            SetHeader(response);
            response.AddHeader("Content-Type", "application/json");
            response.Write(r.ToJson());
        }

        internal static void SetHeader(HttpResponse Response)
        {
            Response.ClearHeaders();
            Response.AddHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Access-Control-Request-Method,X_FILENAME");
            Response.AddHeader("Access-Control-Allow-Methods", "GET,PUT,POST,HEAD,DELETE,OPTIONS");
            Response.AddHeader("Access-Control-Max-Age", "360000");
            Response.AddHeader("Access-Control-Allow-Credentials", "true");
            //Response.AddHeader("Access-Control-Allow-Origin", "*");
        }


        #endregion

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// API统一返回结构
        /// </summary>
        public class ApiResult
        {
            /// <summary>
            /// API是否执行成功
            /// </summary>
            public bool Success { get; set; }
            /// <summary>
            /// 错误代码
            /// </summary>
            public int Code { get; set; }
            /// <summary>
            /// 错误信息
            /// </summary>
            public string Message { get; set; }
            /// <summary>
            /// 扩展信息
            /// </summary>
            public string ExtMsg { get; set; }
            /// <summary>
            /// 返回数据
            /// </summary>
            public object Data { get; set; }
        }
    }
}
